package com.yzc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yzc.execption.ZcException;
import com.yzc.mapper.UserMapper;
import com.yzc.model.entity.system.SysUser;
import com.yzc.model.query.system.UserInfoReq;
import com.yzc.model.vo.system.SysUserVo;
import com.yzc.model.vo.system.UserInfoVo;
import com.yzc.result.ResultCodeEnum;
import com.yzc.service.UserService;
import com.yzc.util.BCrypt;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, SysUser>
        implements UserService {

    @Autowired
    private BCrypt bCrypt;

    @Autowired
    private UserMapper userBeanMapper;

    public List<UserInfoVo> loadaAll() {
        //操作
        return userBeanMapper.loadaAll();
    }

    @Override
    public SysUserVo getUserVoByName(String username) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getUsername, username);
        SysUser sysUser = getOne(queryWrapper);

        if (sysUser == null) {
            return null;
        }

        SysUserVo sysUserVo = new SysUserVo();
        BeanUtils.copyProperties(sysUser, sysUserVo);
        return sysUserVo;
    }

    @Override
    public UserInfoVo getInfoById(Long id) {
        return userBeanMapper.getInfoById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultCodeEnum saveUser(UserInfoReq userInfoReq) {
        if (userInfoReq == null || StringUtils.isBlank(userInfoReq.getUsername())) {
            throw new ZcException(ResultCodeEnum.BAD_REQUEST.getCode(), "用户名不能为空");
        }

        try {
            // 密码加密（提取到工具类更佳）
            encryptPasswordIfNeeded(userInfoReq);

            // 保存用户
            userBeanMapper.saveUser(userInfoReq);
            Long userId = userInfoReq.getId();

            // 设置角色（需校验 kzid 是否存在）
            if (userInfoReq.getKzid() == null) {
                throw new ZcException(ResultCodeEnum.BAD_REQUEST.getCode(), "角色ID不能为空");
            }
            userBeanMapper.settingRole(userId, userInfoReq.getKzid());

            return ResultCodeEnum.SUCCESS;
        } catch (Exception e) {
            log.error("保存用户失败: {}", e.getMessage(), e);
            throw new ZcException(ResultCodeEnum.FAIL.getCode(), "保存用户信息失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultCodeEnum updateUser(UserInfoReq userInfoReq) {
        if (userInfoReq == null || userInfoReq.getId() == null) {
            throw new ZcException(ResultCodeEnum.FAIL.getCode(), "用户ID不能为空");
        }

        if (StringUtils.isNotBlank(userInfoReq.getUsername())) {
            LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysUser::getUsername, userInfoReq.getUsername())
                    .ne(SysUser::getId, userInfoReq.getId()); // 排除当前用户
            if (count(queryWrapper) > 0) {
                throw new ZcException(ResultCodeEnum.FAIL.getCode(), "用户名已存在");
            }
        }

        try {
            // 密码加密
            encryptPasswordIfNeeded(userInfoReq);

            // 更新主表
            userBeanMapper.updateUser(userInfoReq);

            // 更新关联表（如果 kzid 不为空）
            if (userInfoReq.getKzid() != null) {
                userBeanMapper.updateUserKz(userInfoReq);
            }

            return ResultCodeEnum.SUCCESS;
        } catch (Exception e) {
            log.error("更新用户失败: {}", e.getMessage(), e);
            throw new ZcException(ResultCodeEnum.FAIL.getCode(), "更新用户信息失败");
        }
    }


    private void encryptPasswordIfNeeded(UserInfoReq userInfoReq) {
        if (StringUtils.isNotBlank(userInfoReq.getPassword())) {
            userInfoReq.setPassword(bCrypt.encode(userInfoReq.getPassword()));
        }
    }
}